//package com.harmay.center.monitor.controller;
//
//import com.google.common.collect.Maps;
//import com.harmay.center.monitor.entity.MetricsData;
//import io.prometheus.client.CollectorRegistry;
//import io.prometheus.client.Counter;
//import io.prometheus.client.exporter.PushGateway;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.collections4.MapUtils;
//import org.apache.commons.lang3.StringUtils;
//import org.apache.commons.lang3.tuple.Pair;
//import org.springframework.beans.factory.InitializingBean;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.web.bind.annotation.RequestBody;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RequestMethod;
//import org.springframework.web.bind.annotation.RestController;
//
//import javax.servlet.http.HttpServletRequest;
//import java.io.Closeable;
//import java.io.IOException;
//import java.util.*;
//import java.util.concurrent.TimeUnit;
//
//import static org.apache.commons.collections4.MapUtils.getString;
//import static org.assertj.core.util.Arrays.asList;
//
///**
// * @author Zuper
// * @version 1.0
// * @date 2022/6/28 14:47
// * @description 用于http端发送到prometheus的计数请求处理
// */
//@Slf4j
//@RestController
//@RequestMapping("/v1/counter/")
//public class CounterMetricsController extends Thread implements InitializingBean, Closeable {
//
//    private static final String JOB = "CounterMetrics";
//    private static final String NAME = "name";
//    private static final String HELP = "help";
//    private static final String VALUE = "value";
//    private static final String LABEL_NAMES = "label_names";
//    private static final String LABEL_VALUES = "label_values";
//    private static final String[] EMPTY_ARRAY = new String[0];
//    private static final String DEFAULT_HELP = "CountMetrics";
//
//    private MetricsData metricsData;
//    private CollectorRegistry registry = new CollectorRegistry();
//
//    private Object lock = new Object();
//
//    private transient Map<String, Pair<Counter, String[]>> counters = Maps.newConcurrentMap();
//
//    private Timer timer = new Timer();
//    private long timerInterval = TimeUnit.MINUTES.toMillis(1);
//
//    @Autowired
//    private PushGateway pushGateway;
//
//    @RequestMapping(value = "push", method = RequestMethod.POST)
//    public void push(HttpServletRequest request, @RequestBody Map<String, Object> map) throws IOException {
//
//        try {
//            MetricsData metricsData = parse(map);
//            if (metricsData != null) {
//                String name = metricsData.getName();
//                String[] labelNames = metricsData.getLabelNames();
//
//                synchronized (lock) {
//                    Counter counter = null;
//                    Pair<Counter, String[]> pair = counters.get(name);
//                    if (pair == null) {
//                        counter = Counter.build().name(name).help(metricsData.getHelp()).labelNames(labelNames)
//                                .register(registry);
//                        counters.put(name, Pair.of(counter, labelNames));
//                    } else {
//                        counter = pair.getLeft();
//                    }
//                    try {
//                        counter.labels(metricsData.getLabelValues()).inc(metricsData.getValue());
//                    } catch (IllegalArgumentException e) {
//                        log.error("Metrics Exception, {}.", e.getMessage());
//                        counter = checkLabels(name, counter, metricsData);
//                        counter.labels(metricsData.getLabelValues()).inc(metricsData.getValue());
//                    }
//                }
//            }
//        } catch (Exception e) {
//            log.error("Metrics Exception.", e);
//        }
//    }
//
//    private MetricsData parse(Map<String, Object> map) {
//        String name = getString(map, NAME);
//        if (name == null) {
//            log.error("Missing metrics name, data {}", map);
//            return null;
//        }
//        String help = getString(map, HELP, DEFAULT_HELP);
//        Double value = MapUtils.getDouble(map, VALUE);
//        if (value == null) {
//            log.error("Missing metrics value, data {}", map);
//            return null;
//        }
//        List<String> label_names = (List<String>) map.get(LABEL_NAMES);
//        String[] labelNames = label_names.toArray(new String[0]);
//        if (labelNames == null) {
//            labelNames = EMPTY_ARRAY;
//        }
//        List<String> label_values = (List<String>) map.get(LABEL_VALUES);
//        String[] labelValues = label_values.toArray(new String[0]);
//        if (labelValues == null) {
//            labelValues = EMPTY_ARRAY;
//        }
//        for (int i = 0; i < labelValues.length; i++) {
//            String labelValue = labelValues[i];
//            if (labelValue == null) {
//                labelValues[i] = StringUtils.EMPTY;
//            }
//        }
//        if (labelNames.length != labelValues.length) {
//            log.error("Label names {} not match label values {}.", asList(labelNames), asList(labelValues));
//            return null;
//        }
//        MetricsData metricsData = new MetricsData();
//        metricsData.setName(name);
//        metricsData.setLabelNames(labelNames);
//        metricsData.setLabelValues(labelValues);
//        metricsData.setValue(value);
//        metricsData.setHelp(help);
//        return metricsData;
//    }
//
//    private Counter checkLabels(String name, Counter counter, MetricsData metricsData) {
//        Pair<Counter, String[]> pair = counters.get(name);
//        if (pair != null) {
//            String[] counterLabels = pair.getRight();
//            if (Arrays.deepEquals(counterLabels, metricsData.getLabelNames()) == false) {
//                log.warn("Label for metrics {} changed, reinit metrics gauge.", name);
//                try {
//                    registry.unregister(counter);
//                } catch (Exception e) {
//                    log.error("", e);
//                }
//                counter = Counter.build().name(name).help(metricsData.getHelp()).labelNames(metricsData.getLabelNames())
//                        .register(registry);
//                counters.put(name, Pair.of(counter, metricsData.getLabelNames()));
//                return counter;
//            }
//        }
//        return counter;
//    }
//
//    @Override
//    public void close() throws IOException {
//        timer.cancel();
//        try {
//            registry.clear();
//        } catch (Exception e) {
//        }
//    }
//
//    @Override
//    public void afterPropertiesSet() throws Exception {
//        this.start();
//    }
//
//    @Override
//    public void run() {
//        timer.schedule(new CounterMetricTask(), timerInterval, timerInterval);
//    }
//
//    class CounterMetricTask extends TimerTask {
//        @Override
//        public void run() {
//            try {
//                log.info("Flush metrics to PushGateway, size {}...", counters.size());
//                synchronized (lock) {
//                    pushGateway.pushAdd(registry, JOB);
//                    registry.clear();
//                    counters.clear();
//                }
//            } catch (Exception e) {
//                log.error("Flush metrics failed.", e);
//            }
//        }
//    }
//
//}
